#include "global.h"

#define ___NOHPS 10




//===========================================================================================
//
//     E L E C T R O N I C S    T E S T E R
//
//===========================================================================================

typedef enum enStMStagesType
{
	stm_Start =0,
	stm_Inrush
};



static bank3 unsigned char dt_window=0;
static bank3 unsigned int dt_window_time_counter=0;
static bank3 unsigned char Fault =0;
static bank3 unsigned char Pass =0;
static bank3 unsigned char Current_Display=0;
static bank3 unsigned char LastFault = 0;


bank1 unsigned char *timebuff;
//const unsigned char *display_message;
const unsigned char* const display_message;

const unsigned char DISPLAY_TIME = 10;
const unsigned char HST_SETPOINT = 44; // initial test temperature
const unsigned char LOW_FREQ=30; 	// freq to soft start 
const unsigned int HEATING_TIME = 300; // 
const unsigned char HITACHI_HIGH_FREQ = 60;
const unsigned char TOSHIBA_HIGH_FREQ = 38;
const signed int CURRENT_SETPOINT = 150; // 

const unsigned char HITACHI_CRITICAL_TEMP = 70; // 
const unsigned char TOSHIBA_CRITICAL_TEMP = 90;


const signed char HITACHI_DELTA_T = 30; //difference between HST nd OAT;
const signed char TOSHIBA_DELTA_T = 60;
						


const unsigned char PACKETS_TO_REGULATE=3; // 
const unsigned char ACCELERATION_TIMEOUT = 60; // if compressor cannot accelerate in this time
const unsigned char WAIT_COMMUNICATION_TIME = 20; 	// 20 sec communication waiting, longer time can damage a capasitor 
const unsigned char EEV_CLOSING_TIME =22; // 22sec need to close EEV from 300 (default opening) to 20													// bank or driver in case of assembling error
const unsigned int ALLOWED_INRUSH_CURRENT=0x0064;		// allowed current  1.00A
const unsigned int BURNING_TEST_TIME = 300; // 300 SEC - 5 minutes
const unsigned int FREQUENCY_FOLOWING_TEST_TIME = 120; // TIME TO CHECK if actual frequency equal to setpoint
const unsigned char FREQUENCY_FOLLOWING_DELTA = 15; // +/- 15  
const unsigned char* pMessage = " SIRIUS PROJECT     ";


const char* const DriverErrorMssg[]={
//"12345678901234567890";
"Ok",					// 0 no error
"DriverIC fault",		// 1 
"Instance OVC",			// 2
"Temp abnormal rise",// 3
"Temp rise",			// 4
"DC UnderVoltage",		// 5
"DC OverVoltage ", 		// 6
"TX fail",				// 7
"Current fault",		// 8
"Power fail",			// 9
"Chip reset",			// 10
"Sync loss"				// 11
};

bit TriggerHPS=0;


void DoTest(void)
{
//==========================================================
//    S T A T E    M A S H I N E
//==========================================================

	//unsigned int temperature;
	bank1 static unsigned int dt_temp=0;
	bank3 static test_state_index=0;
	bank3 static prev_state_index=0;

	bank3 static unsigned char HighFreq =0;
	bank3 static unsigned char CriticalTemp=85;
	bank3 static signed char DeltaT=0;

	if (!flag_test_running)
	{
		test_state_index=33;
		Fault=0;
		Current_Display =0;
		Red_lamp_off();
		Green_lamp_off();
		Yellow_lamp_off();
		for (dt_temp=0; dt_temp<20;dt_temp++)
		{
			MyODU.access[dt_temp]=0; // reset MyODU structure up to another test start
		};	
	};
	
	//======================================================
	//				hst critical temperature handle
	//======================================================
	if (MyODU.Data.ODUExtraData.OEnvHST > CriticalTemp)
	{
 		Current_Display =0;
		ClearLCD();
//		MyODU.Data.ODUExtraData.OEnvHST=CriticalTemp;
		test_state_index = 32;
		pMessage="  DRIVER OVERHEAT   ";
	};


	//===============================================================================
	//     in fault handle - red lamp blink on  - 2 display operation
	//===============================================================================
	if (!flag_packet_tov.Task.DoTest)
	{
		if (MyODU.Data.ODUBasicData.OOprInFlt)
		{
			LastFault = MyODU.Data.ODUExtraData.CompDrvErr&0b00001111;
			Red_lamp_blink();		
			Fault=1;				//Lets check this for The HIgh Pressure Protection =)

		}
		else
		{
			Red_lamp_off();
		};
	};

	//================================================================================
	//		Display build  section
	//================================================================================

	switch (Current_Display)
	{
		case 0:
			//=============== stages window =============

			WriteToPosLCD(2,0);
				printf (pMessage);
			WriteToPosLCD(3,6);
				timebuff=ShowSTime(getSec(),time) ;
				printf ("%s",time);

			if (Fault)
			{
				WriteToPosLCD(4,0);
				printf ("%s",Error_explanation[LastFault]);
			};
			
		 break;
			
		case 1:			 // screen 1
			// ================= M A I N    T E S T   W I N D O W ============================

				WriteToPosLCD(1,0);
				printf (pMessage);
				WriteToPosLCD(2,0);
					timebuff=ShowSTime(getSec(),time) ;
					printf ("%s",time);
				WriteToPosLCD(2,6);
					printf ("  f=%d/%dHz   ",myPreset.Compressor_freq,MyODU.Data.ODUBasicData.OEnvCompActFreq);	

				WriteToPosLCD(3,0);
					ShowCurrent(MyODU.Data.ODUBasicData.OEnvCompCur,time);
					printf("I=%sA  ",time);
				WriteToPosLCD(3,8);
					switch(MyODU.Data.ODUExtraData.ODUModel)
					{
						case 13:	printf ("4HP   ");	
							break;
						case 14:	printf ("5HP   ");	
							break;
						case 15:	printf ("6HP   ");	
							break;
						default:	printf ("M:%d  ",MyODU.Data.ODUExtraData.ODUModel);
							break;
					}
				WriteToPosLCD(3,13);
					printf("CTT:%d ",MyODU.Data.ODUExtraData.OEnvCTT);				

				WriteToPosLCD(4,0);
					printf("HST:%d ",MyODU.Data.ODUExtraData.OEnvHST);
				WriteToPosLCD(4,10);
					printf ("OAT:%d ",MyODU.Data.ODUExtraData.OEnvOAT);	
				//================================================================================
				//		Window change timer
				//================================================================================

				if (Fault)
				{
					if (dt_window_time_counter++ > 2*DISPLAY_TIME)
					{
						dt_window_time_counter=0;
						Current_Display = 2;
						ClearLCD();			
					}
				}			
			break;	
				
		case 2: // ============== F A I L U R E   R E P O R T   W I N D O W =======================
				//		Window change timer
				//================================================================================

				if (Fault)
				{
					if (dt_window_time_counter++ > DISPLAY_TIME)
					{
						dt_window_time_counter=0;
						Current_Display = 1; // return to curent regulation display
						ClearLCD();			
					}
					WriteToPosLCD(1,0);		
						printf ("General Error: ");
					WriteToPosLCD(2,0);		
						printf ("%s",Error_explanation[MyODU.Data.ODUBasicData.OOprLstFlr&0b00011111]);
					if (DriverErrorMssg[MyODU.Data.ODUExtraData.CompDrvErr&0b00001111])
					{
						WriteToPosLCD(3,0);	
							printf ("Driver state: ");
						WriteToPosLCD(4,0);	
							printf ("%s",DriverErrorMssg[MyODU.Data.ODUExtraData.CompDrvErr&0b00001111]);
					};
				};

			
			break;
			
		default:		dt_window_time_counter=0;
						Current_Display = 0; // return to curent regulation display
						ClearLCD();			

			break;
			
	}; // ===============E N D    O F   D I S P L A Y    S E L E C T I O N ==================
	

//========================================================================
//
//                      S T A T E    M A S H I N E
//
//========================================================================
	if ((test_state_index>0)&& (test_state_index<10))
	{
			if (!SupplyPresent())
			{
						test_state_index =32;   //  jump to POWER FAILURE ERROR
						ClearLCD();
						pMessage=" SAFETY DOOR OPENED ";
			};
	};

	switch (test_state_index)
	{

		case 0:
			EnableTime();
			StopITUComm();
			Current_Display=0;  // simplified display without measurements
			ConnectHPS();
			DisconnectCOM();
			ConnectSupply();
			Yellow_lamp_on();
			Green_lamp_blink();
			Red_lamp_off();
			pMessage = "COM CONNECTION TEST ";
			if (getSec() > 1)
				{
					if ( !SupplyPresent())
					{
						test_state_index =32;   //  jump to POWER FAILURE ERROR
						ClearLCD();
						pMessage="   POWER FAILURE    ";
					}
					else
					{
						if (ComInDanger())
						{
							test_state_index=32; // jumpt to error handler
							ClearLCD();
							pMessage="COM CONNECTION ERROR";
						}
						else
						{
							ConnectCOM();
							test_state_index =1;   // lets wait for communication
							pMessage="   Inrush Test      ";
							ClearLCD();
							resetTime();
						}; // com connection check
					}
				};

			break;

		case 1:  	//test  inrush current
			if ( Measured_current() > ALLOWED_INRUSH_CURRENT )
				{
					test_state_index=32; // jumpt to error handler
					ClearLCD();
					pMessage=" INRUSH OVERCURRENT ";
		};
			
			if (getSec() > 4)  // 5 sec for  inrush current measurement
				{
					ClearLCD();
					test_state_index =2;   //  jump to Communication test
					pMessage=" Communication Test ";
					resetTime();
					Green_lamp_blink();
					Yellow_lamp_off();
				}
			break;

		case 2:      //   wait for communication
			#ifndef ___NOHPS
			DisconnectHPS();
			#endif
			EnableTime();
			Current_Display=0;  // simplified display without measurements
			//stop_me=1;
			if (!flag_packet_tov.Task.DoTest)
			{		
				if (getSec() > WAIT_COMMUNICATION_TIME)
				{

					test_state_index=32; // jumpt to error handler
					ClearLCD();
					pMessage="COMMUNICATION  ERROR";
				};
			}
			else
			{
				resetTime();
				ClearLCD();
				MyIDU.Data.IDUBasicData.IOprMMode = 1; // COOL;///////========================= CHANGED TO COOL DURING DEBUG
				test_state_index=3;  // continue testing
				pMessage=" Inrush Charging    ";
			};
			break;



		case 3:   //  waiting for inrush charging

				if (getSec() == 10)
				{
					if (EEVState())
					{
						resetTime();
						test_state_index=32; // jumpt to error handler
						ClearLCD();
						pMessage="EEV  OUTPUT FIALURE ";
					};
					if (RVState())
					{

						resetTime();
						test_state_index=32; // jumpt to error handler
						ClearLCD();
						pMessage="R/V  OUTPUT FAILURE ";
 
						MyIDU.Data.IDUBasicData.IOprMMode = 0; // STBY;
					};


// =================== here need to check connected ODUC Jumper settings  =================
// ===== only models  4,5,6 HP are allowed

					if ((MyODU.Data.ODUExtraData.ODUModel == 13)|| (MyODU.Data.ODUExtraData.ODUModel== 14))
					{	HighFreq= HITACHI_HIGH_FREQ;
						DeltaT = HITACHI_DELTA_T;
						CriticalTemp = HITACHI_CRITICAL_TEMP;
					}
					else if(MyODU.Data.ODUExtraData.ODUModel== 15)
					{	HighFreq= TOSHIBA_HIGH_FREQ;
						DeltaT = TOSHIBA_DELTA_T;
						CriticalTemp = TOSHIBA_CRITICAL_TEMP;
					}
					else
					{
						test_state_index=32; // jumpt to error handler
						ClearLCD();
						pMessage="NOT 4,5,6 HP CONFIG ";
					}
				};

				if (getSec() > 30)  // 30 sec for  inrush charging
				{
					ClearLCD();
					test_state_index =4;   //  continue test
					pMessage=" HPS LPS Input Test ";
					resetTime();
				};

			break;
///==============================================================================================================
///==============================================================================================================
///==============================================================================================================
		case 4:		// high pressure test
	#ifndef ___NOHPS
				if (!TriggerHPS)
				{
					if (!MyODU.Data.ODUExtraData.IPHiPres)
					{	
						ConnectHPS();					
					}	
					else 
					{
						test_state_index=32; // jumpt to error handler
						ClearLCD();
						pMessage="    HPS FAILURE     ";
	//					pMessage="    LPS FAILURE     ";
						Red_lamp_blink();   	//  another error 
					};
					TriggerHPS=1;
				};
	#endif				
				if (getSec() > 3)  // wait 3 sec for HPS error disappear 
				{
					if (MyODU.Data.ODUExtraData.IPHiPres)
					{
					// switchin to measurement display
						Current_Display=1;
						StartITUComm();
					//  here we starting compressor
						resetTime();
						test_state_index =5;
						pMessage=" Compr. Start 30Hz  ";
						myPreset.Compressor_freq=LOW_FREQ;
						myPreset.EEV_value=20;
						myPreset.Fan_speed =2;
						myPreset.Mode = 2; // heat
						StartITUComm();
						ClearLCD();
					
					}
					else
					{

						test_state_index=32; // jumpt to error handler
						ClearLCD();
						pMessage="    HPS FAILURE     ";
			

					};					
					// there no handle here for another error
				}

			break;
///==============================================================================================================
///==============================================================================================================
///==============================================================================================================				
		case 5:
			//===  Lets check the EEV 
			if (getSec() == EEV_CLOSING_TIME)
			{
				if (!EEVState())
				{
					test_state_index=32; // jumpt to error handler
					ClearLCD();
					pMessage="EEV  OUTPUT FIALURE ";
				};
			};

			// after 15 seconds lets  control the LOW Freq
			if (getSec()> EEV_CLOSING_TIME )
			{
				if (MyODU.Data.ODUBasicData.OEnvCompActFreq >= LOW_FREQ)
				{	resetTime();
					test_state_index=6;
					pMessage=" Acceleration compr.";

						myPreset.Compressor_freq=HighFreq;
						myPreset.EEV_value=20;
						myPreset.Fan_speed =2;
						myPreset.Mode = 2; // heat
						StartITUComm();
				}
				else if (getSec()>ACCELERATION_TIMEOUT)
				{
					// here Report Error

					Current_Display=0;
					test_state_index=32; // jumpt to error handler
					ClearLCD();
					pMessage="COMPRESSOR NOT START";

				};

			
			};
			break;

		case 6:
			if ( MyODU.Data.ODUBasicData.OEnvCompActFreq >= HighFreq )
			{
				resetTime();
				test_state_index =7;
				pMessage="Waiting for HST 44C ";
				StartITUComm();

			};
			if (!RVState())
			{
				test_state_index=32; // jumpt to error handler
				ClearLCD();
				pMessage="R/V  OUTPUT FAILURE "; 
				MyIDU.Data.IDUBasicData.IOprMMode = 0; // STBY;
			};
			break;
			
		case 7: 		//"Waiting for HST 44C "
			CurrentRegulation(CURRENT_SETPOINT);
			if ( MyODU.Data.ODUExtraData.OEnvHST >= HST_SETPOINT)
			{
				resetTime();
				test_state_index=8;
				pMessage="15A Burning TEST 5m ";
				StartITUComm();
			};
			break;

		case 8:			//"15A burning test 5m "
			CurrentRegulation(CURRENT_SETPOINT);

			if (getSec() >FREQUENCY_FOLOWING_TEST_TIME)
			{
				if (myPreset.Compressor_freq > MyODU.Data.ODUBasicData.OEnvCompActFreq)
				{
					if((myPreset.Compressor_freq-MyODU.Data.ODUBasicData.OEnvCompActFreq)>	FREQUENCY_FOLLOWING_DELTA)
					{
						 //  error of the frequency following 
						 // setpoint from current regulation more than actual frequency more than 
						test_state_index=32; // jumpt to error handler
						ClearLCD();
						pMessage="SPEED FOLOWING ERROR";
					};
				}
				else
				{
					if((MyODU.Data.ODUBasicData.OEnvCompActFreq - myPreset.Compressor_freq)>	FREQUENCY_FOLLOWING_DELTA)
					{
					
						 //  error of the frequency following 
						 // setpoint from current regulation more than actual frequency more than 
					
						test_state_index=32; // jumpt to error handler
						ClearLCD();
						pMessage="SPEED FOLOWING ERROR";

					};
				};
			};


			if ( getSec() > BURNING_TEST_TIME)
			{
				resetTime();
				test_state_index=9;
				pMessage="Heatsink temp check ";
				StartITUComm();
			};
			break;

		case 9:
			CurrentRegulation(CURRENT_SETPOINT);
			if (getSec()>60)
			{
				Current_Display=0;
				if ((signed char)(MyODU.Data.ODUExtraData.OEnvHST - MyODU.Data.ODUExtraData.OEnvOAT) < DeltaT)
				{ 
					test_state_index =10;
					ClearLCD();
					pMessage=" TEST PASSED dT OK  ";
				}
				else
				{
					test_state_index=32; // jumpt to error handler
					ClearLCD();
					pMessage=" TEST FAILED dT BAD "; 
				}
			}	
			break;			

		case 10:						// stop test condition with OK
			DisableTime();
			
				myPreset.Compressor_freq=0;
				myPreset.EEV_value=150;
				myPreset.Fan_speed =0;
				myPreset.Mode = 0; // idle 
			Green_lamp_on();
			Red_lamp_off();
			break;

		case 32:						// stop test condition with KO
			DisableTime();
			DisconnectSupply();
			DisconnectCOM();
				myPreset.Compressor_freq=0;
				myPreset.EEV_value=150;
				myPreset.Fan_speed =0;
				myPreset.Mode = 0; // idle
			Red_lamp_on();
			Yellow_lamp_off();
			Green_lamp_on();
			break;

		case 33:						// Ready state condition 
				DisconnectCOM();
				DisableTime();
				pMessage=" READY, PRESS START ";
				Current_Display=0;  // simplified display without measurements
				myPreset.Compressor_freq=0;
				myPreset.EEV_value=150;
				myPreset.Fan_speed =0;
				myPreset.Mode = 0; // idle 
				Green_lamp_off();
				Red_lamp_off();
				DisconnectSupply();
		//========= Reseet all triggers =====================
				TriggerHPS=0;
		//===================================================
				if (flag_test_running)
				{
					ClearLCD();
					test_state_index=0;
					Current_Display=0;
					resetTime();
					Fault=0;
					EnableTime();
				};

			break;
		default:
			test_state_index =0;
			break;
	}; //  end of statemashine
	flag_packet_tov.Task.DoTest=0;


};// end of dotest



void CurrentRegulation(signed int Setpoint_A) // 15.0 A must be represent as 150 28.6A as 286
{
	static bank3 unsigned char itu_prev_MsgId;
	static bank3 unsigned char prev_valid_MsgId;
	static bank3 unsigned char Packets_count;
	signed int temp_current;
	
	// ================  packets counter ===============
	if ( MyODUIDUHeader.Data.MsgId != prev_valid_MsgId)
	{ 	
		prev_valid_MsgId =MyODUIDUHeader.Data.MsgId;
		Packets_count+=1;
	};

	if (Packets_count > PACKETS_TO_REGULATE)
	{
		Packets_count =0;
		StartITUComm();
		//================== regulator ================
			
			temp_current =( signed int )(MyODU.Data.ODUBasicData.OEnvCompCur+MyODU.Data.ODUBasicData.OEnvCompCur);
			// now in temp current  a actual value of the AC current

			temp_current-=Setpoint_A; 
			// now in temp_current Delta;
		

		// AC CURRENT MORE THAN SETPOINT
			if ( temp_current>0)  
			{
		//		if (( temp_current>0)&&( temp_current<3)) // if +/- 0.5A tolerance no need regulate
		//		{
					// no need regulation
		//		}	
		//		else 
				if ( (temp_current>=3)&&( temp_current<8))	// if  +/- 0.5 to 1A tolerance 1hz 
				{
					myPreset.Compressor_freq-=1;
				}
				else if  ((temp_current>=8) && ( temp_current<15))// if +/-  1A and more  3hz regulation
				{
					myPreset.Compressor_freq-=3;
				}
				else if  (temp_current>=15)  // if +/-  1A and more  3hz regulation
				{
					myPreset.Compressor_freq-=6;
				};
			}
		// END OF DECREASING COMPRESSOR SPEED
	
		// AC CURRENT LESS THAN A SETPOINT
			else 	
			{
				//if (( temp_current<0)&&( temp_current> -3)) // if +/- 0.5A tolerance no need regulate
				//{
					// no need regulation
				//}	
				//else 
				if ((temp_current<= -3)&&(temp_current> -8))	// if  +/- 0.5 to 1A tolerance 1hz 
				{
					myPreset.Compressor_freq+=1;
				}
				else if  ((temp_current<= -8)&&( temp_current> -15))  // if +/-  1A and more  3hz regulation
				{
					myPreset.Compressor_freq+=3;
				}
				else if  (temp_current<= -15)  // if +/-  1A and more  3hz regulation
				{
					myPreset.Compressor_freq+=6;
				};
			};
		// END OF INCREASING COMPRESSOR SPEED

	}; // end of regulation after N packets passed;	
};
